package cn.edu.zxj.rabbitmqmyself.model.compile.and.run;

import cn.edu.zxj.rabbitmqmyself.util.CommandUtil;
import cn.edu.zxj.rabbitmqmyself.util.FileUtil;

import java.io.File;
import java.io.IOException;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * Description：该类用来完成编译和运行任务
 *
 * @author: zxj
 * @date: 2024-10-02
 * @time: 00:49:10
 */

public class Task {
    /*
     * 需求分析:
     * 1. 该类需要提供一个方法，用来完成编译和运行任务, 接受 Request 参数, 返回 Response 参数
     * 2. 编译和运行任务的过程中, 会产生一些中间文件, 需要将这些文件保存到指定的 ./tmp 目录下
     * 3. 编译命令: javac -encoding UTF-8 -d ./tmp ./tmp/Solution.java
     * 4. 运行命令: java -cp ./tmp Main
     * 5. Request 中提供 code 字段, 需要将 code 写入到 ./tmp/Solution.java 文件中
     * 6. Response 中用来记录编译和运行的结果, 状态码, 运行结果, 错误信息
     */

    // 定义相关字段
    private final static String CLASS = "Solution";
    private final static String BASE_DIR = "./tmp/";
    private String workDir;
    private String code ;
    private String stdout;
    private String stderr;
    private String compileStderr; // 保存编译错误的文件


    public Task() {
        String uuid ="task-"+ UUID.randomUUID().toString();
        workDir = BASE_DIR + uuid + "/";

        File workDirFile = new File(workDir);
        workDirFile.mkdirs();

        code = workDir + CLASS + ".java";
        stdout = workDir + "stdout.txt";
        stderr = workDir + "stderr.txt";
        compileStderr = workDir + "compile_stderr.txt"; // 保存编译错误的文件
    }


    public Response compileAndRun(Request request) throws IOException {
        Response response = new Response();

        // 1. 先将代码写入到文件中
        String code = request.getCode();
        FileUtil.writeToFile(this.code, code);

        // 2. 编译
        // 2.1 准备编译命令
        String cmd = String.format("javac -encoding UTF-8 -d %s %s", this.workDir, this.code);
        // 2.2 执行编译命令
        int compileRet = CommandUtil.run(cmd, stdout, compileStderr);
        response.setCode(compileRet);
        if (compileRet != 0) {
            response.setCode(1);
            // 编译出错
            String reason = FileUtil.readFromFile(compileStderr);
            response.setReason(reason);
            return response;
        }

        // 3. 运行
        // 3.1 准备运行命令
        cmd = String.format("java -cp %s %s", this.workDir, CLASS);
        // 3.2 执行运行命令
        int runRet = CommandUtil.run(cmd, stdout, stderr);
        response.setCode(runRet);
        if (runRet != 0) {
            // 运行出错
            response.setCode(2);
            String reason = FileUtil.readFromFile(stderr);
            response.setReason(reason);
            return response;
        }

        // 4. 运行成功
        response.setCode(0);
        String stdout = FileUtil.readFromFile(this.stdout);
        response.setStdout(stdout);

        return response;
    }

}
